use std::slice;

use ffmpeg_sys_next::{av_buffer_alloc, AVPacket, AVRational};

#[derive(Debug)]
pub struct Packet {
    pub pts: i64,
    pub dts: i64,
    pub data: Vec<u8>,
    pub size: i32,
    pub stream_index: i32,
    pub flags: i32,
    pub buffer: Vec<u8>,
    pub buffer_size: usize,
    pub side_data: Vec<u8>,
    pub side_data_elems: i32,
    pub duration: i64,
    pub pos: i64,
}

#[derive(Debug, Clone)]
pub struct DecoderData {
    pub data: Vec<u8>,
    pub pts: i64,
    pub time_base: AVRational,
    pub width: i32,
    pub height: i32,
}

unsafe impl Send for DecoderData {}

impl Clone for Packet {
    fn clone(&self) -> Self {
        Self {
            pts: self.pts,
            dts: self.dts,
            data: self.data.clone(),
            size: self.size,
            stream_index: self.stream_index,
            flags: self.flags,
            buffer: self.buffer.clone(),
            buffer_size: self.buffer_size,
            side_data: self.side_data.clone(),
            side_data_elems: self.side_data_elems,
            duration: self.duration,
            pos: self.pos,
        }
    }
}

impl Default for Packet {
    fn default() -> Self {
        Self {
            pts: 0,
            dts: 0,
            data: Vec::new(),
            size: 0,
            stream_index: -1,
            flags: 0,
            buffer: Vec::new(),
            buffer_size: 0,
            side_data: vec![],
            side_data_elems: 0,
            duration: 0,
            pos: 0,
        }
    }
}

impl Packet {
    pub unsafe fn copy(&mut self, packet: *mut AVPacket) {
        self.pts = unsafe { (*packet).pts };
        self.dts = unsafe { (*packet).dts };
        self.size = unsafe { (*packet).size };
        self.stream_index = unsafe { (*packet).stream_index };
        self.duration = unsafe { (*packet).duration };
        self.pos = unsafe { (*packet).pos };
        self.flags = unsafe { (*packet).flags };
        self.buffer_size = unsafe { (*(*packet).buf).size };
        self.data = unsafe { slice::from_raw_parts((*packet).data, self.size as usize).to_vec() };
        self.buffer =
            unsafe { slice::from_raw_parts((*(*packet).buf).data, self.buffer_size).to_vec() };
    }

    pub unsafe fn to_av_packet(&mut self, packet: *mut AVPacket) {
        unsafe {
            (*packet).buf = av_buffer_alloc(self.buffer_size);
            (*packet).pts = self.pts;
            (*packet).dts = self.dts;
            (*packet).size = self.size;
            (*packet).stream_index = self.stream_index;
            (*packet).duration = self.duration;
            (*packet).pos = self.pos;
            (*packet).flags = self.flags;
            (*(*packet).buf).size = self.buffer_size;
            (*(*packet).buf).data = self.buffer.as_mut_ptr();
            (*packet).data = self.data.as_mut_ptr();
        }
    }
}

impl Default for DecoderData {
    fn default() -> Self {
        Self {
            data: Vec::new(),
            pts: 0,
            time_base: AVRational { num: 0, den: 0 },
            width: 0,
            height: 0,
        }
    }
}

#[derive(Debug, Clone)]
pub enum PlayStatus {
    Start,
    PacketEnd,
    AudioFrameEnd,
    VideoFrameEnd,
    Pause,
    Resume,
    End,
}
